package com.wiscamp.ninechapters.panels.domain.services;

import com.wiscamp.ninechapters.panels.domain.repositories.PanelsErrorCodes;
import com.wiscamp.ninechapters.panels.domain.entities.Permission;
import com.wiscamp.ninechapters.panels.domain.repositories.PermissionRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.DomainService;
import cube.ddd.exception.ExceptionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class PermissionService implements DomainService {
    private final PermissionRepository permissionRepository;

    private final String cacheName = "permissions";

    public PermissionService(PermissionRepository permissionRepository) {
        this.permissionRepository = permissionRepository;
    }

    @HandleServiceException
    @Cacheable(value = cacheName, key = "#permissionId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Permission getPermission(long permissionId) {
        var permission = permissionRepository.getPermission(permissionId);
        if (Objects.isNull(permission)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.PERMISSION_NOT_FOUND, permissionId);
        }
        return permission;
    }


    @HandleServiceException
    @CachePut(value = cacheName, key = "#permission.permissionId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Permission createPermission(Permission permission, long operatorId) {
        var existedPermission = permissionRepository.getPermissionByCode(permission.getApplicationId(), permission.getPermissionCode());
        if (Objects.nonNull(existedPermission)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.PERMISSION_CODE_EXISTED, permission);
        }

        permission.createBy(operatorId);
        return permissionRepository.savePermission(permission);
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#permission.permissionId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Permission updatePermission(Permission permission, long operatorId) {
        var existedPermission = getPermission(permission.getPermissionId());
        existedPermission = permissionRepository.getPermissionByCode(permission.getApplicationId(), permission.getPermissionCode());
        if (Objects.nonNull(existedPermission) && existedPermission.getPermissionId() != permission.getPermissionId()) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.PERMISSION_CODE_EXISTED, permission);
        }
        permission.updateBy(operatorId);
        return permissionRepository.savePermission(permission);
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#permissionId")
    public boolean enablePermission(long permissionId, long operatorId) {
        var permission = getPermission(permissionId);
        if (Objects.isNull(permission)) return false;
        // 记录操作日志
        permission.enable();
        permission.updateBy(operatorId);
        permissionRepository.savePermission(permission);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#permissionId")
    public boolean disablePermission(long permissionId, long operatorId) {
        var permission = getPermission(permissionId);
        if (Objects.isNull(permission)) return false;
        // 记录操作日志
        permission.disable();
        permission.updateBy(operatorId);
        permissionRepository.savePermission(permission);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#permissionId")
    public boolean deletePermission(long permissionId, long operatorId) {
        var permission = getPermission(permissionId);
        if (Objects.isNull(permission)) return false;
        // 记录操作日志
        permission.enable();
        permission.updateBy(operatorId);
        permissionRepository.savePermission(permission);
        return true;
    }
}
